

package net.matvec;


public class Vector {

    public double[] vect;

    static {
	Runtime.getRuntime().load("/usr/local/lib/libjnimatvec.so");
	//System.loadLibrary("jnimatvec");
    }

    public Vector(){
	vect = new double[4];
    }

    /* Native declarations. */
    private native void   vm_add(double[] v1, double[] v2, double[] r);
    private native void   vm_sub(double[] v1, double[] v2, double[] r);
    private native void   vm_scale(double[] v, double d, double[] r);
    private native double vm_magnitude(double[] v);
    private native void   vm_norm(double[] v, double[] r);
    private native void   vm_cross(double[] v1, double[] v2, double[] r);
    private native void   vm_project(double[] v1, double[] v2, double[] r);
    private native double vm_dot(double[] v1, double[] v2);
    private native double vm_angle(double[] v1, double[] v2);
    private native void   vm_print(double[] v);
    private native void   vm_println(double[] v);

    /* Here are the public wrappers for the native methods. */

    /**
     * Adds the specified vector to this and then returns the result.
     */
    public Vector add(Vector v2){
	Vector v = new Vector();
	vm_add(v2.vect, this.vect, v.vect);
	return v;
    }

    /**
     * Adds the two specified vectors and puts the result in this vector.
     */
    public void add(Vector v1, Vector v2){
	vm_add(v1.vect, v2.vect, this.vect);
    }

    /**
     * Subtracts this by the specified vector and then returns the result.
     */
    public Vector sub(Vector v2){
	Vector v = new Vector();
	vm_sub(this.vect, v2.vect, v.vect);
	return v;
    }

    /**
     * Subtracts v2 from v1 and stores the result in this vector.
     */
    public void sub(Vector v1, Vector v2){
	vm_sub(v1.vect, v2.vect, this.vect);
    }

    public Vector scale(double d){
	Vector v = new Vector();
	vm_scale(this.vect, d, v.vect);
	return v;
    }

    public void scale(Vector v, double d){
	vm_scale(v.vect, d, this.vect);
    }

    public double magnitude(){
	return vm_magnitude(this.vect);
    }

    public Vector norm(){
	Vector v = new Vector();
	vm_norm(this.vect, v.vect);
	return v;
    }

    public void norm(Vector v){
	vm_norm(v.vect, this.vect);
    }

    public Vector cross(Vector v2){
	Vector v = new Vector();
	vm_cross(this.vect, v2.vect, v.vect);
	return v;
    }

    public void cross(Vector v1, Vector v2){
	vm_cross(v1.vect, v2.vect, this.vect);
    }

    public Vector project(Vector v2){
	Vector v = new Vector();
	vm_project(this.vect, v2.vect, v.vect);
	return v;
    }

    public void project(Vector v1, Vector v2){
	vm_project(v1.vect, v2.vect, this.vect);
    }

    public double dot(Vector v2){
	return vm_dot(this.vect, v2.vect);
    }

    public double angle(Vector v){
	return vm_angle(this.vect, v.vect);
    }

    public void print(){
	System.out.printf("[%f, %f, %f, %f]", 
			  vect[0], vect[1], vect[2], vect[3]);
    }

    public void println(){
	System.out.printf("[%f, %f, %f, %f]\n", 
			  vect[0], vect[1], vect[2], vect[3]);
    }

}
